﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Kaleida.ServiceMonitor.Model.Runtime;

namespace Kaleida.ServiceMonitor.UI
{
    class NotificationPanelFactory
    {
        private readonly List<Type> availablePanelTypes;

        internal NotificationPanelFactory(IEnumerable<Assembly> searchAssemblies)
        {
            
            var searchTypes = searchAssemblies.SelectMany(i => i.GetTypes()).ToList();

            var withCorrectBase = new HashSet<Type>(searchTypes.Where(i => i.DerivesFrom(typeof(INotificationPanel))));
            var withPublicVisibility = new HashSet<Type>(searchTypes.Where(i => i.IsVisible));
            var withPublicDefaultConstructor = new HashSet<Type>(searchTypes.Where(i => i.HasPublicDefaultConstructor()));

            availablePanelTypes = withCorrectBase.Intersect(withPublicVisibility).Intersect(withPublicDefaultConstructor).ToList();
        }

        public IEnumerable<Type> GetPanelTypes(Type baseType)
        {
            return availablePanelTypes.Where(i => i.DerivesFrom(baseType));
        }

        public T CreatePanel<T>(Type type) where T : INotificationPanel
        {
            try
            {
                return (T)Activator.CreateInstance(type);
            }
            catch (Exception e)
            {
                throw new InvalidOperationException(string.Format("Could not instantiate Notification Panel from Type '{0}': {1}", type.Name, e), e);
            }
        }
    }
}
